package com.fowo.api.datainterface.util;

import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONObject;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.*;
import com.dingtalk.api.response.*;
import com.fowo.api.datainterface.model.DingTalkDeptModel;
import com.fowo.api.datainterface.model.DingTalkUserModel;
import com.fowo.api.flow.config.DingDingConfig;
import com.taobao.api.ApiException;
import liquibase.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

@Component
@Slf4j
public class DingTalkUtil {



    /**
     * 获取token
     *
     * @param appkey
     * @param appsecret
     * @return
     */
    public static JSONObject getAccessToken(String appkey, String appsecret) {
        JSONObject retMsg = new JSONObject();
        retMsg.put("code", true);
        retMsg.put("error", "");
        try {
            DingTalkClient client = new DefaultDingTalkClient(SpringUtil.getBean(DingDingConfig.class).TOKEN);
            OapiGettokenRequest req = new OapiGettokenRequest();
            req.setAppkey(appkey);
            req.setAppsecret(appsecret);
            req.setHttpMethod("GET");
            OapiGettokenResponse rsp = client.execute(req);
            retMsg.put("access_token", rsp.getAccessToken());
            if (!rsp.isSuccess()) {
                retMsg.put("code", false);
                retMsg.put("error", rsp.getErrmsg());
                retMsg.put("access_token", "");
            }
        } catch (ApiException e) {
            retMsg.put("code", false);
            retMsg.put("error", e.toString());
            retMsg.put("access_token", "");
        }

        return retMsg;
    }

    /**
     * 给用户推送消息（文字消息）
     *
     * @param appkey
     * @param appsecret
     * @param agentid
     * @param userIds
     * @param content
     * @return 收到消息格式如下：
     * 发送的内容
     */
    public static JSONObject sendDingMessage(String appkey, String appsecret, String agentid, String userIds, String content) {
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype("text");
        msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text());
        msg.getText().setContent(content);
        return sendDingMessage(appkey, appsecret, agentid, userIds, msg);
    }

    /**
     * 给用户推送消息（卡片消息） https://open.dingtalk.com/document/orgapp/message-type
     *
     * @param appkey
     * @param appsecret
     * @param agentid
     * @param userIds
     * @param actionCard
     * @return 收到消息格式如下：
     * 发送的内容
     */
    public static JSONObject sendDingMessage(String appkey, String appsecret, String agentid, String userIds, OapiMessageCorpconversationAsyncsendV2Request.ActionCard actionCard) {
        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype("action_card");
        msg.setActionCard(actionCard);
        msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text());

        return sendDingMessage(appkey, appsecret, agentid, userIds, msg);
    }

    /**
     * 给用户推送消息（markdown消息） https://open.dingtalk.com/document/orgapp/message-type
     *
     * @param appkey
     * @param appsecret
     * @param agentid
     * @param userIds
     * @param markdown
     * @return 收到消息格式如下：
     * 发送的内容
     */
    public static JSONObject sendDingMessage(String appkey, String appsecret, String agentid, String userIds, OapiMessageCorpconversationAsyncsendV2Request.Markdown markdown) {

        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype("markdown");
        msg.setMarkdown(markdown);
        msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text());
        return sendDingMessage(appkey, appsecret, agentid, userIds, msg);
    }

    /**
     * 给用户推送消息
     *
     * @param appkey
     * @param appsecret
     * @param agentid
     * @param userIds
     * @param msg
     * @return
     */
    @NotNull
    private static JSONObject sendDingMessage(String appkey, String appsecret, String agentid, String userIds, OapiMessageCorpconversationAsyncsendV2Request.Msg msg) {
        JSONObject retMsg = new JSONObject();
        DingTalkClient client = new DefaultDingTalkClient(SpringUtil.getBean(DingDingConfig.class).SEND_MESSAGE);
        OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
        request.setUseridList(userIds);
        request.setAgentId(Long.parseLong(agentid));
        request.setToAllUser(false);


        request.setMsg(msg);

        try {
            retMsg = getAccessToken(appkey, appsecret);
            if (retMsg.getBoolean("code")) {
                OapiMessageCorpconversationAsyncsendV2Response response = client.execute(request, retMsg.getString("access_token"));
                if (response.getErrcode() > 0) {
                    retMsg.put("code", false);
                    retMsg.put("error", response.getErrmsg());
                } else {
                    retMsg.put("code", true);
                    retMsg.put("error", "");
                }
            } else {
                retMsg.put("code", false);
                retMsg.put("error", "获取token失败:" + retMsg.getString("error"));
            }
            return retMsg;
        } catch (ApiException e) {
            retMsg.put("code", false);
            retMsg.put("error", e.toString());
            return retMsg;
        }
    }
    //------------------------------------接口：部门管理的增删改查-------------------------------------

    /**
     * 创建钉钉部门接口
     *
     * @param deptModel
     * @param accessToken
     * @return
     */
    public static JSONObject createDepartment(DingTalkDeptModel deptModel, String accessToken) {
        JSONObject retMsg = new JSONObject();
        boolean codeFlag = true;
        String errorMsg = "";
        String deptId = "0";
        try {
            DingTalkClient client = new DefaultDingTalkClient(SpringUtil.getBean(DingDingConfig.class).CREATE_DEPARTMENT);
            OapiV2DepartmentCreateRequest req = new OapiV2DepartmentCreateRequest();
            req.setParentId(deptModel.getParentId());
            req.setName(deptModel.getName());
            req.setOrder(deptModel.getOrder());
            req.setCreateDeptGroup(deptModel.getCreateDeptGroup());
            req.setSourceIdentifier(deptModel.getSourceIdentifier());
            OapiV2DepartmentCreateResponse rsp = client.execute(req, accessToken);
            if (rsp.isSuccess()) {
                codeFlag = true;
                JSONObject bodyObject = JSONObject.parseObject(rsp.getBody());
                bodyObject = JSONObject.parseObject(bodyObject.getString("result"));
                deptId = bodyObject.getLong("dept_id").toString();
            } else {
                codeFlag = false;
                errorMsg = rsp.getErrmsg();
            }
        } catch (ApiException e) {
            codeFlag = false;
            errorMsg = e.toString();
        }
        retMsg.put("code", codeFlag);
        retMsg.put("error", errorMsg);
        retMsg.put("retDeptId", deptId);
        return retMsg;
    }

    /**
     * 更新钉钉部门接口
     *
     * @param deptModel
     * @param accessToken
     * @return
     */
    public static JSONObject updateDepartment(DingTalkDeptModel deptModel, String accessToken) {
        JSONObject retMsg = new JSONObject();
        boolean codeFlag = true;
        String errorMsg = "";
        try {
            DingTalkClient client = new DefaultDingTalkClient(SpringUtil.getBean(DingDingConfig.class).UPDATE_DEPARTMENT);
            OapiV2DepartmentUpdateRequest req = new OapiV2DepartmentUpdateRequest();
            req.setDeptId(deptModel.getDeptId());
            req.setParentId(deptModel.getParentId());
            req.setOrder(deptModel.getOrder());
            req.setName(deptModel.getName());
            // 设置部门主管,先建部门、再建设用户、再更新部门主管
            if (StringUtil.isNotEmpty(deptModel.getDeptManagerUseridList())) {
                req.setDeptManagerUseridList(deptModel.getDeptManagerUseridList());
            }
            OapiV2DepartmentUpdateResponse rsp = client.execute(req, accessToken);
            if (!rsp.isSuccess()) {
                codeFlag = false;
                errorMsg = rsp.getErrmsg();
            }
        } catch (ApiException e) {
            codeFlag = false;
            errorMsg = e.toString();
        }
        retMsg.put("code", codeFlag);
        retMsg.put("error", errorMsg);
        return retMsg;
    }

    /**
     * 删除钉钉部门接口
     *
     * @param id
     * @param accessToken
     * @return
     */
    public static JSONObject deleteDepartment(Long id, String accessToken) {
        JSONObject retMsg = new JSONObject();
        boolean codeFlag = true;
        String errorMsg = "";

        try {
            DingTalkClient client = new DefaultDingTalkClient(SpringUtil.getBean(DingDingConfig.class).DELETE_DEPARTMENT);
            OapiV2DepartmentDeleteRequest req = new OapiV2DepartmentDeleteRequest();
            req.setDeptId(id);
            OapiV2DepartmentDeleteResponse rsp = client.execute(req, accessToken);
            if (!rsp.isSuccess()) {
                codeFlag = false;
                errorMsg = rsp.getErrmsg();
            }
        } catch (ApiException e) {
            codeFlag = false;
            errorMsg = e.toString();
        }

        retMsg.put("code", codeFlag);
        retMsg.put("error", errorMsg);

        return retMsg;
    }

    /**
     * 获取钉钉部门列表信息接口(一次只能获取下一级部门，不能多级查询)
     *
     * @param id
     * @param accessToken
     * @return
     */
    public static JSONObject getDepartmentList(Long id, String accessToken) {
        JSONObject retMsg = new JSONObject();
        boolean codeFlag = true;
        String errorMsg = "";
        List<OapiV2DepartmentListsubResponse.DeptBaseResponse> departmentAllList = new ArrayList<>();

        retMsg = getDepartmentListSub(id, accessToken, departmentAllList);
        if (!retMsg.getBoolean("code")) {
            codeFlag = false;
            errorMsg = "获取钉钉所有部门列表失败";
        }

        retMsg.put("code", codeFlag);
        retMsg.put("error", errorMsg);
        retMsg.put("department", departmentAllList);

        return retMsg;
    }

    /**
     * 递归获取部门信息列表
     *
     * @param id
     * @param accessToken
     * @param departmentAllList
     * @return
     */
    public static JSONObject getDepartmentListSub(Long id, String accessToken, List<OapiV2DepartmentListsubResponse.DeptBaseResponse> departmentAllList) {
        JSONObject retMsg = new JSONObject();
        boolean codeFlag = true;
        String errorMsg = "";
        List<OapiV2DepartmentListsubResponse.DeptBaseResponse> departmentList = new ArrayList<>();

        try {
            DingTalkClient client = new DefaultDingTalkClient(SpringUtil.getBean(DingDingConfig.class).GET_DEPARTMENT_LIST);
            OapiV2DepartmentListsubRequest req = new OapiV2DepartmentListsubRequest();
            req.setDeptId(id);
            OapiV2DepartmentListsubResponse rsp = client.execute(req, accessToken);
            if (!rsp.isSuccess()) {
                retMsg.put("code", false);
                retMsg.put("error", rsp.getErrmsg());
                return retMsg;
            } else {
                departmentList = rsp.getResult();
                if (departmentList.size() > 0) {
                    for (OapiV2DepartmentListsubResponse.DeptBaseResponse deptEntity : departmentList) {
                        departmentAllList.add(deptEntity);
                        retMsg = getDepartmentListSub(deptEntity.getDeptId(), accessToken, departmentAllList);
                        if (!retMsg.getBoolean("code")) {
                            codeFlag = false;
                            errorMsg = rsp.getErrmsg();
                            break;
                        }
                    }
                }
            }
        } catch (ApiException e) {
            codeFlag = false;
            errorMsg = e.toString();
        }

        retMsg.put("code", codeFlag);
        retMsg.put("error", errorMsg);

        return retMsg;
    }

    /**
     * 获取指定的钉钉部门信息接口
     *
     * @param deptId
     * @param accessToken
     * @return
     */
    public static JSONObject getDepartmentInfo(Long deptId, String accessToken) {
        JSONObject retMsg = new JSONObject();
        boolean codeFlag = true;
        String errorMsg = "";
        OapiV2DepartmentGetResponse.DeptGetResponse departmentInfo = new OapiV2DepartmentGetResponse.DeptGetResponse();

        try {
            DingTalkClient client = new DefaultDingTalkClient(SpringUtil.getBean(DingDingConfig.class).GET_DEPARTMENT_INFO);
            OapiV2DepartmentGetRequest req = new OapiV2DepartmentGetRequest();
            req.setDeptId(deptId);
            OapiV2DepartmentGetResponse rsp = client.execute(req, accessToken);
            if (!rsp.isSuccess()) {
                codeFlag = false;
                errorMsg = rsp.getErrmsg();
            } else {
                departmentInfo = rsp.getResult();
            }
        } catch (ApiException e) {
            codeFlag = false;
            errorMsg = e.toString();
        }

        retMsg.put("code", codeFlag);
        retMsg.put("error", errorMsg);
        retMsg.put("departmentInfo", departmentInfo);

        return retMsg;
    }


    //------------------------------------接口：用户管理的增删改查-------------------------------------

    /**
     * 创建钉钉用户信息接口
     *
     * @param userModel
     * @param accessToken
     * @return
     */
    public static JSONObject createUser(DingTalkUserModel userModel, String accessToken) {
        JSONObject retMsg = new JSONObject();
        boolean codeFlag = true;
        String errorMsg = "";

        try {
            DingTalkClient client = new DefaultDingTalkClient(SpringUtil.getBean(DingDingConfig.class).CREATE_USER);
            OapiV2UserCreateRequest req = new OapiV2UserCreateRequest();
            req.setUserid(userModel.getUserid());
            req.setName(userModel.getName());
            req.setMobile(userModel.getMobile());
            req.setTelephone(userModel.getTelephone());
            req.setJobNumber(userModel.getJobNumber());
            req.setTitle(userModel.getTitle());
            req.setEmail(userModel.getEmail());
            req.setWorkPlace(userModel.getWorkPlace());
            req.setDeptIdList(userModel.getDeptIdList());
            req.setHiredDate(userModel.getHiredDate());
            // 以下属性未设置
            // hide_mobile org_email extension senior_mode login_email
            // exclusive_account exclusive_account_type login_id init_password

            OapiV2UserCreateResponse rsp = client.execute(req, accessToken);
            if (!rsp.isSuccess()) {
                codeFlag = false;
                errorMsg = rsp.getErrmsg();
            }
        } catch (ApiException e) {
            codeFlag = false;
            errorMsg = e.toString();
        }

        retMsg.put("code", codeFlag);
        retMsg.put("error", errorMsg);
        return retMsg;
    }


    /**
     * 更新钉钉用户信息接口
     *
     * @param userModel
     * @param accessToken
     * @return
     */
    public static JSONObject updateUser(DingTalkUserModel userModel, String accessToken) {
        JSONObject retMsg = new JSONObject();
        boolean codeFlag = true;
        String errorMsg = "";

        try {
            DingTalkClient client = new DefaultDingTalkClient(SpringUtil.getBean(DingDingConfig.class).UPDATE_USER);
            OapiV2UserUpdateRequest req = new OapiV2UserUpdateRequest();
            req.setUserid(userModel.getUserid());
            req.setName(userModel.getName());
            req.setMobile(userModel.getMobile());
            req.setTelephone(userModel.getTelephone());
            req.setJobNumber(userModel.getJobNumber());
            req.setTitle(userModel.getTitle());
            req.setEmail(userModel.getEmail());
            req.setWorkPlace(userModel.getWorkPlace());
            req.setDeptIdList(userModel.getDeptIdList());
            req.setHiredDate(userModel.getHiredDate());
            // 以下属性未设置
            // hide_mobile org_email extension senior_mode login_email
            // exclusive_account exclusive_account_type login_id init_password

            OapiV2UserUpdateResponse rsp = client.execute(req, accessToken);
            if (!rsp.isSuccess()) {
                codeFlag = false;
                errorMsg = rsp.getErrmsg();
            }
        } catch (ApiException e) {
            codeFlag = false;
            errorMsg = e.toString();
        }

        retMsg.put("code", codeFlag);
        retMsg.put("error", errorMsg);
        return retMsg;
    }

    /**
     * 删除钉钉用户信息接口
     *
     * @param userId
     * @param accessToken
     * @return
     */
    public static JSONObject deleteUser(String userId, String accessToken) {
        JSONObject retMsg = new JSONObject();
        boolean codeFlag = true;
        String errorMsg = "";

        try {
            DingTalkClient client = new DefaultDingTalkClient(SpringUtil.getBean(DingDingConfig.class).DELETE_USER);
            OapiV2UserDeleteRequest req = new OapiV2UserDeleteRequest();
            req.setUserid(userId);
            OapiV2UserDeleteResponse rsp = client.execute(req, accessToken);
            if (!rsp.isSuccess()) {
                codeFlag = false;
                errorMsg = rsp.getErrmsg();
            }
        } catch (ApiException e) {
            codeFlag = false;
            errorMsg = e.toString();
        }

        retMsg.put("code", codeFlag);
        retMsg.put("error", errorMsg);
        return retMsg;
    }

    public static JSONObject getUserDingList(List<String> departmentList, String accessToken) {
        JSONObject retMsg = new JSONObject();
        boolean codeFlag = true;
        String errorMsg = "";
        List<OapiV2UserListResponse.ListUserResponse> userAllList = new ArrayList<>();

        // 钉钉限制每页记录数：不超过100
//        retMsg = getUserListSub(1L,0L,100L,accessToken,userAllList);
//        if(!retMsg.getBoolean("code")){
//            codeFlag = false;
//            errorMsg = "获取钉钉所有用户列表失败";
//        }

        if (departmentList.size() > 0) {
            for (String deptId : departmentList) {
                retMsg = getUserListSub(Long.parseLong(deptId), 0L, 100L, accessToken, userAllList);
                if (!retMsg.getBoolean("code")) {
                    codeFlag = false;
                    errorMsg = "获取钉钉所有用户列表失败";
                    break;
                }
            }
        }

        retMsg.put("code", codeFlag);
        retMsg.put("error", errorMsg);
        retMsg.put("userlist", userAllList);
        return retMsg;
    }


    public static JSONObject getUserList(List<DingTalkDeptModel> departmentList, String accessToken) {
        JSONObject retMsg = new JSONObject();
        boolean codeFlag = true;
        String errorMsg = "";
        List<OapiV2UserListResponse.ListUserResponse> userAllList = new ArrayList<>();

        // 钉钉限制每页记录数：不超过100
        retMsg = getUserListSub(1L, 0L, 100L, accessToken, userAllList);
        if (!retMsg.getBoolean("code")) {
            codeFlag = false;
            errorMsg = "获取钉钉所有用户列表失败";
        }

        if (departmentList.size() > 0 && retMsg.getBoolean("code")) {
            for (DingTalkDeptModel deptEntity : departmentList) {
                retMsg = getUserListSub(deptEntity.getDeptId(), 0L, 100L, accessToken, userAllList);
                if (!retMsg.getBoolean("code")) {
                    codeFlag = false;
                    errorMsg = "获取钉钉所有用户列表失败";
                    break;
                }
            }
        }

        retMsg.put("code", codeFlag);
        retMsg.put("error", errorMsg);
        retMsg.put("userlist", userAllList);
        return retMsg;
    }

    public static JSONObject getUserListSub(Long deptId, Long cursor, Long size, String accessToken,
                                            List<OapiV2UserListResponse.ListUserResponse> userAllList) {
        JSONObject retMsg = new JSONObject();
        List<OapiV2UserListResponse.ListUserResponse> userList = new ArrayList<>();
        OapiV2UserListResponse.PageResult pageResult = new OapiV2UserListResponse.PageResult();

        try {
            DingTalkClient client = new DefaultDingTalkClient(SpringUtil.getBean(DingDingConfig.class).GET_USER_DETAIL_LIST);
            OapiV2UserListRequest req = new OapiV2UserListRequest();
            req.setDeptId(deptId);
            req.setCursor(cursor);
            req.setSize(size);
            OapiV2UserListResponse rsp = client.execute(req, accessToken);
            if (rsp.isSuccess()) {
                pageResult = rsp.getResult();
                userList = pageResult.getList();
                for (OapiV2UserListResponse.ListUserResponse userEntity : userList) {
                    userAllList.add(userEntity);
                }
                if (pageResult.getHasMore()) {
                    retMsg = getUserListSub(deptId, pageResult.getNextCursor(), size, accessToken, userAllList);
                    if (!retMsg.getBoolean("code")) {
                        retMsg.put("code", false);
                        retMsg.put("error", rsp.getErrmsg());
                        return retMsg;
                    }
                }
            }
        } catch (ApiException e) {
            retMsg.put("code", false);
            retMsg.put("error", e.toString());
            return retMsg;
        }

        retMsg.put("code", true);
        retMsg.put("error", "");
        return retMsg;
    }


}
